/*
 * =====================================================================================
 *
 *       Filename:  Composite.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2015年02月21日 09时47分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  LiuYi (), swliuyi@gmail.com
 *   Organization:  
 *
 * =====================================================================================
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <limits.h>
#include <iostream>
#include <list>
#include <tr1/memory>

using namespace std;

class Component
{
    protected:
        string m_name;
    public:
        Component(string name):m_name(name) { }
        virtual void Add(Component * c) = 0;
        virtual void Remove(Component * c) = 0;
        virtual void Display(int depth) = 0;
        virtual ~Component(){}
};

class Leaf : public Component
{
    public:
        Leaf(string name) : Component(name){}
        void Add(Component * c)
        {
            cout<<"can't add to a leaf"<<endl;
        }
        void Remove(Component * c)
        {
            cout<<"can't remove to a leaf"<<endl;
        }
        void Display(int depth)
        {
            cout<<string(depth, '-')<<" "<<m_name<<endl;
        }
        virtual ~Leaf(){}
};

class Composite : public Component
{
    private:
        list<tr1::shared_ptr<Component> > m_children;
    public:
        Composite(string name) : Component(name) {}
        void Add(Component * c)
        {
            m_children.push_back(tr1::shared_ptr<Component>(c));
        }
        void Remove(Component * c)
        {
            //it's wrong, double delete
            //m_children.remove(tr1::shared_ptr<Component>(c));
            tr1::shared_ptr<Component> temp (c);
            m_children.remove(temp);
        }
        void Display(int depth)
        {
            cout<<string(depth, '-')<<" "<<m_name<<endl;
            for( list<tr1::shared_ptr<Component> > ::iterator it = m_children.begin() ; it != m_children.end() ; it++ )
            {
                (*it)->Display(depth+2);
            }
        }
        virtual ~Composite(){}
};

int main(int argc, char *argv[])
{
    Component * root = new Composite("root");
    root->Add(new Composite("A"));
    root->Add(new Composite("B"));

    Component * comp = new Composite("X");
    comp->Add(new Composite("XA"));
    comp->Add(new Composite("XB"));

    root->Add(comp);

    Component * comp2 = new Composite("XY");
    comp2->Add(new Composite("XYA"));
    comp2->Add(new Composite("XYB"));

    comp->Add(comp2);

    root->Add(new Leaf("Leaf C"));

    Component * leaf = new Leaf("Leaf D");
    root->Add(leaf);
    root->Remove(leaf);

    root->Display(1);
}
